/**
 * Redux slice for project configuration state management
 */

import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit';
import { 
  ProjectConfigState, 
  ProjectConfig, 
  ProjectTypeOption, 
  UIFrameworkOption,
  BaseComponent,
  ProjectDirectoryNode,
} from '@/types/project';

// API 基础地址（容器内通过 Nginx 反向代理，浏览器使用相对路径；本地可通过环境变量覆盖）
const API_BASE = import.meta.env.VITE_API_BASE_URL || '/api/v1';

// Mock data for project types (will be replaced with API calls)
const MOCK_PROJECT_TYPES: ProjectTypeOption[] = [
  { id: 'web', name: 'Web应用程序', description: '具有多个页面的标准Web应用程序' },
  { id: 'admin', name: '管理仪表板', description: '具有复杂数据表格和表单的管理面板' },
  { id: 'saas', name: 'SaaS平台', description: '具有用户管理的软件即服务应用程序' },
  { id: 'mobile', name: '移动Web应用', description: '针对移动设备优化的响应式Web应用程序' },
];

// Mock data for UI frameworks (will be replaced with API calls)
const MOCK_UI_FRAMEWORKS: UIFrameworkOption[] = [
  { id: 'react', name: 'React', value: 'react', icon: 'react' },
  { id: 'vue', name: 'Vue', value: 'vue', icon: 'vue' },
];



// Initial state
const initialState: ProjectConfigState = {
  config: {
    projectName: '',
    projectType: '',
    description: '',
    uiFramework: 'react',
    language: 'typescript',
    buildTool: 'vite',
    targetPlatform: 'pc',
    maxLevels: 3,
    baseComponents: [],
    customRequirements: '',
    generatedComponents: [],
  },
  projectTypes: [],
  uiFrameworks: [],
  baseComponents: [],
  suggestedComponents: [],
  directoryStructure: [],
  directorySummary: '',
  structureLoading: false,
  structureError: null,
  languages: [],
  loading: false,
  error: null,
  isConfigured: false,
};

// Async thunks
export const fetchProjectTypes = createAsyncThunk(
  'project/fetchProjectTypes',
  async (_, { rejectWithValue }) => {
    try {
      // In a real application, this would be an API call
      // const response = await api.get('/api/project-types');
      // return response.data;
      
      // For now, return mock data with a delay
      return new Promise<ProjectTypeOption[]>((resolve) => {
        setTimeout(() => {
          resolve(MOCK_PROJECT_TYPES);
        }, 800);
      });
    } catch (error: any) {
      return rejectWithValue(error.message || 'Failed to fetch project types');
    }
  }
);

export const fetchUIFrameworks = createAsyncThunk(
  'project/fetchUIFrameworks',
  async (_, { rejectWithValue }) => {
    try {
      // In a real application, this would be an API call
      // const response = await api.get('/api/ui-frameworks');
      // return response.data;
      
      // For now, return mock data with a delay
      return new Promise<UIFrameworkOption[]>((resolve) => {
        setTimeout(() => {
          resolve(MOCK_UI_FRAMEWORKS);
        }, 600);
      });
    } catch (error: any) {
      return rejectWithValue(error.message || 'Failed to fetch UI frameworks');
    }
  }
);

export const fetchBaseComponents = createAsyncThunk(
  'project/fetchBaseComponents',
  async (framework: string, { rejectWithValue }) => {
    try {
      const response = await fetch(`${API_BASE}/base-components/${framework}`);
      if (!response.ok) {
        throw new Error('Failed to fetch base components');
      }
      const data = await response.json();
      return data.components as BaseComponent[];
    } catch (error: any) {
      return rejectWithValue(error.message || 'Failed to fetch base components');
    }
  }
);

export const analyzeRequirements = createAsyncThunk(
  'project/analyzeRequirements',
  async (payload: { 
    description: string; 
    uiFramework?: string;
    language?: string;
    buildTool?: string;
    targetPlatform?: string;
    excludeComponents?: string[];
  }, { rejectWithValue }) => {
    try {
      const response = await fetch(`${API_BASE}/analyze-requirements`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(payload),
      });
      if (!response.ok) throw new Error('分析失败');
      const data = await response.json();
      return data.suggestedComponents as BaseComponent[];
    } catch (error: any) {
      return rejectWithValue(error.message || 'Failed to analyze requirements');
    }
  }
);

export const generateDirectoryStructure = createAsyncThunk(
  'project/generateDirectoryStructure',
  async (payload: {
    projectName?: string;
    description?: string;
    uiFramework?: string;
    language?: string;
    buildTool?: string;
    targetPlatform?: string;
    baseComponents?: (string | Record<string, any>)[];
    extendedComponents?: (string | Record<string, any>)[];
  }, { rejectWithValue }) => {
    try {
      const response = await fetch(`${API_BASE}/generate-directory-structure`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(payload),
      });

      const data = await response.json();

      if (!response.ok) {
        throw new Error(data.detail || '目录结构生成失败');
      }

      return data as {
        summary?: string;
        directories?: ProjectDirectoryNode[];
        used_model?: boolean;
        model_used?: string;
      };
    } catch (error: any) {
      return rejectWithValue(error.message || '目录结构生成失败');
    }
  }
);

export const saveProjectConfig = createAsyncThunk(
  'project/saveConfig',
  async (config: ProjectConfig, { rejectWithValue }) => {
    try {
      const response = await fetch(`${API_BASE}/save-config`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(config),
      });
      // 后端返回 { id }
      if (response.ok) {
        try {
          const data = await response.json();
          if (data?.id) {
            localStorage.setItem('projectConfigId', data.id);
          }
        } catch {
          // ignore parse error, 仍然认为保存成功
        }
      }
      // 无论成功与否，前端都返回当前 config 以维持现有 reducer 逻辑
      return config;
    } catch (error: any) {
      return rejectWithValue(error.message || 'Failed to save project configuration');
    }
  }
);

const projectSlice = createSlice({
  name: 'project',
  initialState,
  reducers: {
    setConfigField: (state, action: PayloadAction<{ field: keyof ProjectConfig; value: any }>) => {
      const { field, value } = action.payload;
      (state.config as any)[field] = value;
    },
    resetConfig: (state) => {
      state.config = initialState.config;
      state.isConfigured = false;
    },
    loadConfigFromStorage: (state) => {
      try {
        const savedConfig = localStorage.getItem('projectConfig');
        if (savedConfig) {
          state.config = JSON.parse(savedConfig);
          state.isConfigured = true;
        }
      } catch (error) {
        console.error('Failed to load config from storage', error);
      }
    },
  },
  extraReducers: (builder) => {
    builder
      // Fetch project types
      .addCase(fetchProjectTypes.pending, (state) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(fetchProjectTypes.fulfilled, (state, action: PayloadAction<ProjectTypeOption[]>) => {
        state.loading = false;
        state.projectTypes = action.payload;
        // Set default project type if not set
        if (!state.config.projectType && action.payload.length > 0) {
          state.config.projectType = action.payload[0].id;
        }
      })
      .addCase(fetchProjectTypes.rejected, (state, action) => {
        state.loading = false;
        state.error = action.payload as string;
      })
      
      // Fetch UI frameworks
      .addCase(fetchUIFrameworks.pending, (state) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(fetchUIFrameworks.fulfilled, (state, action: PayloadAction<UIFrameworkOption[]>) => {
        state.loading = false;
        state.uiFrameworks = action.payload;
      })
      .addCase(fetchUIFrameworks.rejected, (state, action) => {
        state.loading = false;
        state.error = action.payload as string;
      })
      
      // Fetch base components
      .addCase(fetchBaseComponents.pending, (state) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(fetchBaseComponents.fulfilled, (state, action: PayloadAction<BaseComponent[]>) => {
        state.loading = false;
        state.baseComponents = action.payload;
      })
      .addCase(fetchBaseComponents.rejected, (state, action) => {
        state.loading = false;
        state.error = action.payload as string;
      })
      .addCase(analyzeRequirements.pending, (state) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(analyzeRequirements.fulfilled, (state, action: PayloadAction<BaseComponent[]>) => {
        state.loading = false;
        state.suggestedComponents = action.payload;
      })
      .addCase(analyzeRequirements.rejected, (state, action) => {
        state.loading = false;
        state.error = action.payload as string;
      })

      .addCase(generateDirectoryStructure.pending, (state) => {
        state.structureLoading = true;
        state.structureError = null;
      })
      .addCase(generateDirectoryStructure.fulfilled, (state, action) => {
        state.structureLoading = false;
        state.directoryStructure = action.payload.directories || [];
        state.directorySummary = action.payload.summary || '';
        state.structureError = null;
      })
      .addCase(generateDirectoryStructure.rejected, (state, action) => {
        state.structureLoading = false;
        state.structureError = action.payload as string;
      })
      
      // Save project config
      .addCase(saveProjectConfig.pending, (state) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(saveProjectConfig.fulfilled, (state, action: PayloadAction<ProjectConfig>) => {
        state.loading = false;
        state.config = action.payload;
        state.isConfigured = true;
        
        // Save to localStorage
        try {
          localStorage.setItem('projectConfig', JSON.stringify(action.payload));
        } catch (error) {
          console.error('Failed to save config to storage', error);
        }
      })
      .addCase(saveProjectConfig.rejected, (state, action) => {
        state.loading = false;
        state.error = action.payload as string;
      });
  },
});

export const { setConfigField, resetConfig, loadConfigFromStorage } = projectSlice.actions;

export default projectSlice.reducer;